from PyQt5.QtWidgets import QApplication,\
  QDesktopWidget, QWidget, \
  QTabWidget, QVBoxLayout, \
  QLabel, QHBoxLayout, QLineEdit, QPushButton,QMessageBox,QGridLayout

import re
from PyQt5.QtCore import QTimer
from datetime import datetime
import time
import platform
import keyi

if platform.system() == "Windows":
  from windows_machine_id import get_machine_id
elif platform.system() == "Linux":
  from linux_machine_id import get_machine_id
else:
  raise Exception("不支持的系统")

# 获取屏幕的几何信息并居中显示
def centerWindow(window:QWidget):
    # 获取屏幕的矩形几何信息
    screen_geometry = QDesktopWidget().screenGeometry()
    # 获取窗口的矩形几何信息
    window_geometry = window.frameGeometry()
    
    # 计算窗口要移动到的中心点位置
    center_point = screen_geometry.center()
    window_geometry.moveCenter(center_point)
    
    # 将窗口的左上角移动到计算后的中心位置
    window.move(window_geometry.topLeft())

class LoginWindow(QWidget):
  def __init__(self,session:keyi.Session, onLoginCallback,onRegisterCallback,onResetPasswordCallback):
    super().__init__()
    self.initUI()
    self.session = session
    self.onLoginedCallback = onLoginCallback
    self.onRegisterCallback = onRegisterCallback
    self.onResetPasswordCallback = onResetPasswordCallback
  
  def initUI(self):
    self.setWindowTitle("登录")
    self.setFixedSize(600,500)
    centerWindow(self)
    mainLayout = QVBoxLayout()
    mainLayout.addStretch()

    userNameLayout = QHBoxLayout()
    userNameLabel = QLabel("账号:")
    self.userNameInput = QLineEdit()
    self.userNameInput.setPlaceholderText("请输入账号或卡密")
    self.userNameInput.setFixedSize(350,50)
    userNameLayout.addStretch()
    userNameLayout.addWidget(userNameLabel)
    userNameLayout.addWidget(self.userNameInput)
    userNameLayout.addStretch()
    mainLayout.addLayout(userNameLayout)

    passwordLayout = QHBoxLayout()
    passwordLabel = QLabel("密码:")
    self.passwordInput = QLineEdit()
    self.passwordInput.setEchoMode(QLineEdit.Password)
    self.passwordInput.setPlaceholderText("请输入密码")
    self.passwordInput.setFixedSize(350,50)
    passwordLayout.addStretch()
    passwordLayout.addWidget(passwordLabel)
    passwordLayout.addWidget(self.passwordInput)
    passwordLayout.addStretch()
    mainLayout.addLayout(passwordLayout)

    keyCodeLayout = QHBoxLayout()
    keyCodeLabel = QLabel("卡密:")
    self.keyCodeInput = QLineEdit()
    self.keyCodeInput.setPlaceholderText("充值或登录输入卡密")
    self.keyCodeInput.setFixedSize(350,50)
    keyCodeLayout.addStretch()
    keyCodeLayout.addWidget(keyCodeLabel)
    keyCodeLayout.addWidget(self.keyCodeInput)
    keyCodeLayout.addStretch()
    mainLayout.addLayout(keyCodeLayout)

    otherLayout = QHBoxLayout()
    resetPasswordButton = QPushButton("忘记密码")
    resetPasswordButton.setFixedSize(165,40)
    resetPasswordButton.clicked.connect(self.onResetPassword)
    registerButton = QPushButton("注册")
    registerButton.setFixedSize(125,40)
    registerButton.clicked.connect(self.onRegister)
    otherLayout.addWidget(resetPasswordButton)
    otherLayout.addWidget(registerButton)
    mainLayout.addLayout(otherLayout)

    loginButtonLayout = QHBoxLayout()
    loginButton = QPushButton("登录")
    loginButton.setFixedSize(438,60)
    loginButton.clicked.connect(self.onLogin)
    loginButtonLayout.addStretch()
    loginButtonLayout.addWidget(loginButton)
    loginButtonLayout.addStretch()
    mainLayout.addLayout(loginButtonLayout)

    rechargeButtonLayout = QHBoxLayout()
    rechargeButton = QPushButton("充值")
    rechargeButton.setFixedSize(438,60)
    rechargeButton.clicked.connect(self.onRecharge)
    rechargeButtonLayout.addStretch()
    rechargeButtonLayout.addWidget(rechargeButton)
    rechargeButtonLayout.addStretch()
    mainLayout.addLayout(rechargeButtonLayout)

    forceRechargeButtonLayout = QHBoxLayout()
    forceRechargeButton = QPushButton("替换充值")
    forceRechargeButton.setFixedSize(438,60)
    forceRechargeButton.clicked.connect(self.onReplaceCharge)
    forceRechargeButtonLayout.addStretch()
    forceRechargeButtonLayout.addWidget(forceRechargeButton)
    forceRechargeButtonLayout.addStretch()
    mainLayout.addLayout(forceRechargeButtonLayout)

    mainLayout.addStretch()
    self.setLayout(mainLayout)
  
  def onLogin(self):
    account = self.userNameInput.text()
    keyCode = self.keyCodeInput.text()
    password = self.passwordInput.text()
    if account == "":
      account = keyCode
    if password == "":
      password = None
    if account == "":
      QMessageBox.warning(self,"错误","账号不能为空")
      return
    self.onLoginedCallback(account,password)
  
  def onRegister(self):
    self.onRegisterCallback()

  def onResetPassword(self):
    self.onResetPasswordCallback()

  def onRecharge(self):
    keyCode = self.keyCodeInput.text()
    account = self.userNameInput.text()
    if keyCode == "":
      QMessageBox.warning(self,"错误","卡密不能为空")
      return
    if account == "":
      QMessageBox.warning(self,"错误","账号不能为空")
      return
    if self.session.recharge(account,keyCode):
      QMessageBox.information(self,"成功","充值成功")
    else:
      QMessageBox.warning(self,"错误","充值失败，错误码："+str(self.session.errorCode))

  def onReplaceCharge(self):
    keyCode = self.keyCodeInput.text()
    account = self.userNameInput.text()
    if keyCode == "":
      QMessageBox.warning(self,"错误","卡密不能为空")
      return
    if account == "":
      QMessageBox.warning(self,"错误","账号不能为空")
      return
    if QMessageBox.question(self,"确认","确定要替换充值吗？",QMessageBox.Yes|QMessageBox.No) == QMessageBox.No:
      return
    if self.session.recharge(account,keyCode,True):
      QMessageBox.information(self,"成功","替换充值成功")
    else:
      QMessageBox.warning(self,"错误","替换充值失败，错误码："+str(self.session.errorCode))
    
class RegisterWindow(QWidget):
  def __init__(self,session:keyi.Session):
    super().__init__()
    self.initUI()
    self.session = session

  def initUI(self):
    self.setWindowTitle("注册")
    self.setFixedSize(600,500)
    centerWindow(self)

    nicknameLabel = QLabel("昵称:")
    self.nicknameInput = QLineEdit()
    self.nicknameInput.setPlaceholderText("请输入昵称")
    self.nicknameInput.setFixedSize(350,50)
    nicknameLayout = QHBoxLayout()
    nicknameLayout.addStretch()
    nicknameLayout.addWidget(nicknameLabel)
    nicknameLayout.addWidget(self.nicknameInput)
    nicknameLayout.addStretch()


    userNameLabel = QLabel("邮箱:")
    self.userNameInput = QLineEdit()
    self.userNameInput.setPlaceholderText("请输入用户名")
    self.userNameInput.setFixedSize(350,50)
    userNameLayout = QHBoxLayout()
    userNameLayout.addStretch()
    userNameLayout.addWidget(userNameLabel)
    userNameLayout.addWidget(self.userNameInput)
    userNameLayout.addStretch()

    passwordLabel = QLabel("密码:")
    self.passwordInput = QLineEdit()
    self.passwordInput.setEchoMode(QLineEdit.Password)
    self.passwordInput.setPlaceholderText("请输入密码")
    self.passwordInput.setFixedSize(350,50)
    passwordLayout = QHBoxLayout()
    passwordLayout.addStretch()
    passwordLayout.addWidget(passwordLabel)
    passwordLayout.addWidget(self.passwordInput)
    passwordLayout.addStretch()

    ensurePasswordLabel = QLabel("确认:")
    self.ensurePasswordInput = QLineEdit()
    self.ensurePasswordInput.setPlaceholderText("请再次输入密码")
    self.ensurePasswordInput.setEchoMode(QLineEdit.Password)
    self.ensurePasswordInput.setFixedSize(350,50)
    ensurePasswordLayout = QHBoxLayout()
    ensurePasswordLayout.addStretch()
    ensurePasswordLayout.addWidget(ensurePasswordLabel)
    ensurePasswordLayout.addWidget(self.ensurePasswordInput)
    ensurePasswordLayout.addStretch()

    self.verifyCodeInput = QLineEdit()
    self.verifyCodeInput.setPlaceholderText("请输入验证码")
    self.verifyCodeInput.setFixedSize(230,50)
    sendEmailButton = QPushButton("发送验证码")
    self.sendEmailButton = sendEmailButton
    sendEmailButton.setFixedSize(200,50)
    sendEmailButton.clicked.connect(self.onSendEmail)
    verifyCodeLayout = QHBoxLayout()
    verifyCodeLayout.addStretch()
    verifyCodeLayout.addWidget(self.verifyCodeInput)
    verifyCodeLayout.addWidget(sendEmailButton)
    verifyCodeLayout.addStretch()



    registerButton = QPushButton("注册")
    registerButton.setFixedSize(438,60)
    registerButton.clicked.connect(self.onRegister)
    registerLayout = QHBoxLayout()
    registerLayout.addStretch()
    registerLayout.addWidget(registerButton)
    registerLayout.addStretch()

    mainLayout = QVBoxLayout()
    mainLayout.addStretch()
    mainLayout.addLayout(nicknameLayout)
    mainLayout.addLayout(userNameLayout)
    mainLayout.addLayout(passwordLayout)
    mainLayout.addLayout(ensurePasswordLayout)
    mainLayout.addLayout(verifyCodeLayout)
    mainLayout.addLayout(registerLayout)
    mainLayout.addStretch()
    self.setLayout(mainLayout)

  def onRegister(self):
    nickname = self.nicknameInput.text()
    userName = self.userNameInput.text()
    password = self.passwordInput.text()
    ensurePassword = self.ensurePasswordInput.text()
    verifyCode = self.verifyCodeInput.text()
    # 判断验证码是否为4位数字
    if not verifyCode.isdigit() or len(verifyCode) != 4:
      QMessageBox.warning(self,"错误","验证码必须是4位数字")
      return
    if password != ensurePassword:
      QMessageBox.warning(self,"错误","两次输入的密码不一致")
      return
    if self.session.registerAccount(userName,password,nickname,int(verifyCode)):
      QMessageBox.information(self,"成功","注册成功")
    else:
      QMessageBox.warning(self,"错误","注册失败")
  
  def onSendEmail(self):
    userName = self.userNameInput.text()
    if not re.match(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$', userName):
      QMessageBox.warning(self,"错误","邮箱格式不正确")
      return
    if self.session.sendRegisterCode(userName):
      #添加倒计时
      self.sendEmailButton.setText("重新发送（60s）")
      self.sendEmailButton.setEnabled(False)
      self.countdown = 60
      self.timer = QTimer()
      self.timer.timeout.connect(self.onCountdown)
      self.timer.start(1000)
    else:
      QMessageBox.warning(self,"错误","发送验证码失败")

  def onCountdown(self):
    self.countdown -= 1
    if self.countdown <= 0:
      self.sendEmailButton.setText("重新发送")
      self.sendEmailButton.setEnabled(True)
      self.timer.stop()
    else:
      self.sendEmailButton.setText("重新发送（"+ str(self.countdown) +"s）")

class ResetPasswordWindow(QWidget):
  def __init__(self,session:keyi.Session):
    super().__init__()
    self.initUI()
    self.session = session

  def initUI(self):
    self.setWindowTitle("重置密码")
    self.setFixedSize(600,500)
    centerWindow(self)

    emailLabel = QLabel("邮箱:")
    self.emailInput = QLineEdit()
    self.emailInput.setPlaceholderText("请输入邮箱")
    self.emailInput.setFixedSize(350,50)
    emailLayout = QHBoxLayout()
    emailLayout.addStretch()
    emailLayout.addWidget(emailLabel)
    emailLayout.addWidget(self.emailInput)
    emailLayout.addStretch()

    passwordLabel = QLabel("密码:")
    self.passwordInput = QLineEdit()
    self.passwordInput.setEchoMode(QLineEdit.Password)
    self.passwordInput.setPlaceholderText("请输入密码")
    self.passwordInput.setFixedSize(350,50)
    passwordLayout = QHBoxLayout()
    passwordLayout.addStretch()
    passwordLayout.addWidget(passwordLabel)
    passwordLayout.addWidget(self.passwordInput)
    passwordLayout.addStretch()

    ensurePasswordLabel = QLabel("确认:")
    self.ensurePasswordInput = QLineEdit()
    self.ensurePasswordInput.setPlaceholderText("请再次输入密码")
    self.ensurePasswordInput.setEchoMode(QLineEdit.Password)
    self.ensurePasswordInput.setFixedSize(350,50)
    ensurePasswordLayout = QHBoxLayout()
    ensurePasswordLayout.addStretch()
    ensurePasswordLayout.addWidget(ensurePasswordLabel)
    ensurePasswordLayout.addWidget(self.ensurePasswordInput)
    ensurePasswordLayout.addStretch()

    verifyCodeInput = QLineEdit()
    verifyCodeInput.setPlaceholderText("请输入验证码")
    verifyCodeInput.setFixedSize(230,50)
    self.verifyCodeInput = verifyCodeInput
    sendEmailButton = QPushButton("发送验证码")
    self.sendEmailButton = sendEmailButton
    sendEmailButton.setFixedSize(200,50)
    sendEmailButton.clicked.connect(self.onSendEmail)
    verifyCodeLayout = QHBoxLayout()
    verifyCodeLayout.addStretch()
    verifyCodeLayout.addWidget(verifyCodeInput)
    verifyCodeLayout.addWidget(sendEmailButton)
    verifyCodeLayout.addStretch()

    resetPasswordButton = QPushButton("重置密码")
    resetPasswordButton.setFixedSize(438,60)
    resetPasswordButton.clicked.connect(self.onResetPassword)
    resetPasswordLayout = QHBoxLayout()
    resetPasswordLayout.addStretch()
    resetPasswordLayout.addWidget(resetPasswordButton)
    resetPasswordLayout.addStretch()

    mainLayout = QVBoxLayout()
    mainLayout.addStretch()
    mainLayout.addLayout(emailLayout)
    mainLayout.addLayout(passwordLayout)
    mainLayout.addLayout(ensurePasswordLayout)
    mainLayout.addLayout(verifyCodeLayout)
    mainLayout.addLayout(resetPasswordLayout)
    mainLayout.addStretch()
    self.setLayout(mainLayout)

  def onResetPassword(self):
    email = self.emailInput.text()
    password = self.passwordInput.text()
    ensurePassword = self.ensurePasswordInput.text()
    verifyCode = self.verifyCodeInput.text()
    if password != ensurePassword:
      QMessageBox.warning(self,"错误","两次输入的密码不一致")
      return
    if not verifyCode.isdigit() or len(verifyCode) != 4:
      QMessageBox.warning(self,"错误","验证码必须是4位数字")
      return

    if not re.match(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$', email):
      QMessageBox.warning(self,"错误","邮箱格式不正确")
      return
    if self.session.resetPassword(email,password,int(verifyCode)):
      QMessageBox.information(self,"成功","重置密码成功")
    else:
      QMessageBox.warning(self,"错误","重置密码失败，错误码："+str(self.session.errorCode))
  
  def onSendEmail(self):
    email = self.emailInput.text()
    if not re.match(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$', email):
      QMessageBox.warning(self,"错误","邮箱格式不正确")
      return
    if self.session.sendResetPasswordCode(email):
      self.sendEmailButton.setText("重新发送（60s）")
      self.sendEmailButton.setEnabled(False)
      self.countdown = 60
      self.timer = QTimer()
      self.timer.timeout.connect(self.onCountdown)
      self.timer.start(1000)
    else:
      QMessageBox.warning(self,"错误","发送验证码失败，错误码："+str(self.session.errorCode))

  def onCountdown(self):
    self.countdown -= 1
    if self.countdown <= 0:
      self.sendEmailButton.setText("重新发送")
      self.sendEmailButton.setEnabled(True)
      self.timer.stop()
    else:
      self.sendEmailButton.setText("重新发送（"+ str(self.countdown) +"s）")

class MainWindow(QTabWidget):
  chargeType:keyi.ChargeType
  username:str
  def __init__(self,session:keyi.Session, onLogoutCallback):
    super().__init__()
    self.onLogoutCallback = onLogoutCallback
    self.session = session
    self.initUI()

  def createMainTab(self):
    mainTab = QWidget()
    mainLayout = QVBoxLayout()
    self.expiredLabel = QLabel("过期时间:")
    self.noticeLabel = QLabel("公告:")
    self.noticeLabel.setStyleSheet("color: red;")
    self.dataLabel = QLabel("数据:")
    self.dataLabel.setStyleSheet("color: green;")
    mainLayout.addWidget(self.expiredLabel)
    mainLayout.addStretch()
    mainLayout.addWidget(self.noticeLabel)
    mainLayout.addWidget(self.dataLabel)
    logoutButton = QPushButton("注销")
    logoutButton.clicked.connect(self.onLogout)
    mainLayout.addWidget(logoutButton)
    mainLayout.addStretch()
    mainTab.setLayout(mainLayout)
    return mainTab

  def createChangePasswordTab(self):
    oldPasswordLabel = QLabel("旧密码:")
    self.oldPasswordInput = QLineEdit()
    self.oldPasswordInput.setEchoMode(QLineEdit.Password)
    self.oldPasswordInput.setPlaceholderText("请输入旧密码")
    self.oldPasswordInput.setFixedSize(350,50)
    oldPasswordLayout = QHBoxLayout()
    oldPasswordLayout.addStretch()
    oldPasswordLayout.addWidget(oldPasswordLabel)
    oldPasswordLayout.addWidget(self.oldPasswordInput)
    oldPasswordLayout.addStretch()

    newPasswordLabel = QLabel("新密码:")
    self.newPasswordInput = QLineEdit()
    self.newPasswordInput.setEchoMode(QLineEdit.Password)
    self.newPasswordInput.setPlaceholderText("请输入新密码")
    self.newPasswordInput.setFixedSize(350,50)
    newPasswordLayout = QHBoxLayout()
    newPasswordLayout.addStretch()
    newPasswordLayout.addWidget(newPasswordLabel)
    newPasswordLayout.addWidget(self.newPasswordInput)
    newPasswordLayout.addStretch()

    ensurePasswordLabel = QLabel("再输入:")
    self.ensurePasswordInput = QLineEdit()
    self.ensurePasswordInput.setPlaceholderText("请再次输入新密码")
    self.ensurePasswordInput.setEchoMode(QLineEdit.Password)
    self.ensurePasswordInput.setFixedSize(350,50)

    ensurePasswordLayout = QHBoxLayout()
    ensurePasswordLayout.addStretch()
    ensurePasswordLayout.addWidget(ensurePasswordLabel)
    ensurePasswordLayout.addWidget(self.ensurePasswordInput)
    ensurePasswordLayout.addStretch()


    changePasswordButton = QPushButton("修改密码")
    changePasswordButton.setFixedSize(438,60)
    changePasswordButton.clicked.connect(self.onChangePassword)
    changePasswordLayout_ = QHBoxLayout()
    changePasswordLayout_.addStretch()
    changePasswordLayout_.addWidget(changePasswordButton)
    changePasswordLayout_.addStretch()

    changePasswordLayout = QVBoxLayout()
    changePasswordLayout.addStretch()
    changePasswordLayout.addLayout(oldPasswordLayout)
    changePasswordLayout.addLayout(newPasswordLayout)
    changePasswordLayout.addLayout(ensurePasswordLayout)
    changePasswordLayout.addLayout(changePasswordLayout_)
    changePasswordLayout.addStretch()
    changePasswordTab = QWidget()
    changePasswordTab.setLayout(changePasswordLayout)
    return changePasswordTab

  def onLogout(self):
    self.onLogoutCallback()

  def initUI(self):
    self.setWindowTitle("主界面")
    self.setFixedSize(600,500)
    centerWindow(self)
    self.addTab(self.createMainTab(),"软件信息")
    self.addTab(self.createChangePasswordTab(),"修改密码")

  def logined(self,username:str, notice:str,data:str,chargeType:keyi.ChargeType,balance:int):
    self.chargeType = chargeType
    self.username = username
    if chargeType == keyi.ChargeType.kTime:
      now_time = time.time()
      expired_time = now_time + balance
      expired_time_str = datetime.fromtimestamp(expired_time).strftime("%Y-%m-%d %H:%M:%S")
      self.expiredLabel.setText("过期时间: "+expired_time_str)
    else:
      self.expiredLabel.setText("剩余次数: "+str(balance))
    self.noticeLabel.setText("公告: "+notice)
    self.dataLabel.setText("数据: "+data)

  def onChangePassword(self):
    oldPassword = self.oldPasswordInput.text()
    newPassword = self.newPasswordInput.text()
    ensurePassword = self.ensurePasswordInput.text()
    if newPassword != ensurePassword:
      QMessageBox.warning(self,"错误","两次输入的密码不一致")
      return
    if self.session.changePassword(self.username,oldPassword,newPassword):
      QMessageBox.information(self,"成功","修改密码成功")
    else:
      QMessageBox.warning(self,"错误","修改密码失败，错误码："+str(self.session.errorCode))

def onLogoutCallback():
  global mainWindow
  global loginWindow
  global session
  global tickTimer
  if tickTimer.isActive():
    tickTimer.stop()
  mainWindow.close()
  loginWindow.show()
  session.logout()


def onLoginCallback(username,password):
  global loginWindow
  global mainWindow
  global session
  global tickTimer
  machineId = get_machine_id()
  if machineId == None:
    QMessageBox.warning(loginWindow,"错误","获取机器id失败")
    return
  print(machineId)
  if session.login(username,machineId,password):
    mainWindow.logined(username,session.notice,session.data,session.chargeType,session.balance)
    mainWindow.show()
    loginWindow.close()
    tickTimer.start()
  else:
    QMessageBox.warning(loginWindow,"错误","登录失败，错误码："+str(session.errorCode))

def onResetPasswordCallback():
  global resetPasswordWindow
  resetPasswordWindow.show()

def onRegisterCallback():
  global registerWindow
  registerWindow.show()


def onTick():
  global session
  global app
  if session.tick() == False:
    app.quit()

if __name__ == "__main__":
  app = QApplication([])
  secretId = "你的SecretId"
  secretKey = "你的SecretKey"
  projectId = 0 # 项目id
  session = keyi.Session(secretId,secretKey,projectId)
  mainWindow = MainWindow(session,onLogoutCallback)
  registerWindow = RegisterWindow(session)
  resetPasswordWindow = ResetPasswordWindow(session)

  tickTimer = QTimer()
  tickTimer.setInterval(20000)
  tickTimer.timeout.connect(onTick)

  loginWindow = LoginWindow(session,onLoginCallback,onRegisterCallback,onResetPasswordCallback)
  loginWindow.show()
  app.exec_()

